#ifndef COMMON_H
#define COMMON_H

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "prj_cfg.h"
#include "std_tcpci_v10.h"

/************************* CHIP **************************/
#define CHIP_NONE               0
#define CHIP_SG41620            1
#define CHIP_SG795              2
#define CHIP_TYPE               CHIP_SG41620
#define SG41620_C_PATCH         0
/************************* CHIP **************************/

/************************* DEBUG *************************/
// save log to flash
#define ELOG_MODULE_ENABLE      0

// shell cli
#define SHELL_CLI_ENALBE        0

// module log message switch
#define TYPEC_ROLE_INFO         0
#define TYPEC_PS_INFO           0
#define TYPEC_TIMER_INFO        0
#define TYPEC_STATE_INFO        0
#define PD_EVENT_INFO           0
#define PE_STATE_INFO           0
#define PE_VDM_INFO             0
#define DPM_CAP_INFO            0
#define DPM_EXT_CAP_INFO        0
#define DP_ALT_MODE_INFO        0
#define DP_DFPU_STATE_INFO      0
#define TCPM_EVENT_INFO         0

#define PE_DBG_INFO             0
#define DPM_DBG_INFO            0
#define DP_DBG_INFO             0
#define PWR_DBG_INFO            0 // Sink Power Policy
#if PE_DBG_INFO
#define PE_DBG(...)             printf(__VA_ARGS__)
#else
#define PE_DBG(...)             ((void)0)
#endif
#if DPM_DBG_INFO
#define DPM_DBG(...)            printf(__VA_ARGS__)
#else
#define DPM_DBG(...)            ((void)0)
#endif
#if DP_DBG_INFO
#define DP_DBG(...)             printf(__VA_ARGS__)
#else
#define DP_DBG(...)             ((void)0)
#endif
#if PWR_DBG_INFO
#define PWR_DBG(...)            printf(__VA_ARGS__)
#else
#define PWR_DBG(...)            ((void)0)
#endif
/************************* DEBUG *************************/

/************************ GENERAL ************************/
#define BITS_PER_LONG           32
#define GENMASK(h, l)           (((~0UL) << (l)) & \
                                 (~0UL >> (BITS_PER_LONG - 1 - (h))))
#define BIT(bit)                ((uint32_t)1 << (bit))
#define ARRAY_SIZE(array)       (sizeof array / sizeof array[0])
#define MIN(a, b)               (((a) < (b)) ? (a) : (b))
#define MAX(a, b)               (((a) > (b)) ? (a) : (b))
#define UNUSED(x)               (x) = (x) // to suppress compiler warning
#define DEC_IF_POSITIVE(x)      (((x) > 0) ? ((x)--) : 0)
/************************ GENERAL ************************/

/************************* MACRO *************************/
#define PD_DATA_OBJ_SIZE        (7)
#define PDO_MAX_NR              (PD_DATA_OBJ_SIZE)
#define VDO_MAX_NR              (PD_DATA_OBJ_SIZE-1)
#define VDO_MAX_SVID_NR         (VDO_MAX_NR*2)

#define PD_MSG_BUF_SIZE         (4*2)
#define PD_EVENT_BUF_SIZE       (8*2)
#define TCP_EVENT_BUF_SIZE      (2*2)

/* MIDB, Manufacturer_Info */
#define PD_MIDB_MIN_SIZE        4
#define PD_MIDB_MAX_SIZE        26
#define PD_MIDB_DYNAMIC_SIZE    (PD_MIDB_MAX_SIZE-PD_MIDB_MIN_SIZE)

#define DP_ALT_MODE_CABLE_SVIDS_CNT     2
/************************* MACRO *************************/

/************************* ENUM **************************/
enum tcpm_transmit_type {
    TCPC_TX_SOP = 0,
    TCPC_TX_SOP_PRIME = 1,
    TCPC_TX_SOP_PRIME_PRIME = 2,
    TCPC_TX_SOP_DEBUG_PRIME = 3,
    TCPC_TX_SOP_DEBUG_PRIME_PRIME = 4,
    TCPC_TX_HARD_RESET = 5,
    TCPC_TX_CABLE_RESET = 6,
    TCPC_TX_BIST_MODE_2 = 7
};

enum pd_battery_reference {
    PD_BAT_REF_FIXED0 = 0,
    PD_BAT_REF_FIXED1,
    PD_BAT_REF_FIXED2,
    PD_BAT_REF_FIXED3,

    PD_BAT_REF_SWAP0 = 4,
    PD_BAT_REF_SWAP1,
    PD_BAT_REF_SWAP2,
    PD_BAT_REF_SWAP3,

    PD_BAT_REF_MAX,
    /* 8 ~ 255 are reserved and shall not be used */
};
/************************* ENUM **************************/

/************************* STRUCT ************************/
#pragma anon_unions

struct pd_msg {
    enum tcpm_transmit_type frame_type;
    uint16_t msg_hdr;
    uint32_t payload[7];
};
struct pd_event {
    uint8_t event_type;
    uint8_t msg;
    uint8_t msg_sec;
    struct pd_msg *pd_msg;
};
struct tcp_dpm_pd_request {
    int mv;
    int ma;
};
struct tcp_dpm_pd_request_ex {
    uint8_t pos;
    int vmin;

    union {
        uint32_t max;
        uint32_t max_uw;
        uint32_t max_ma;
    };

    union {
        uint32_t oper;
        uint32_t oper_uw;
        uint32_t oper_ma;
    };
};
struct tcp_dpm_dp_data {
    uint32_t val;
    uint32_t mask;
};
struct tcp_dpm_custom_vdm_data {
    bool wait_resp;
    bool cable;
    uint8_t cnt;
    uint32_t data[PD_DATA_OBJ_SIZE];
};
struct tcp_dpm_svdm_data {
    uint16_t svid;
    uint8_t ops;
};
struct pd_get_battery_capabilities {
    enum pd_battery_reference bat_cap_ref; /* pd_battery_reference */
};
struct pd_get_battery_status {
    enum pd_battery_reference bat_status_ref; /* pd_battery_reference */
};
struct pd_get_manufacturer_info {
    uint8_t info_target;
    enum pd_battery_reference info_ref;
};
struct sgm41620_tcpc;
struct tcp_dpm_event;
typedef int (*tcp_dpm_event_cb)(\
            struct sgm41620_tcpc *tcpc, int ret, struct tcp_dpm_event *event);
struct tcp_dpm_event_cb_data {
    void *user_data;
    tcp_dpm_event_cb event_cb;
};
struct tcp_dpm_event {
    uint8_t event_id;
    void *user_data;
    tcp_dpm_event_cb event_cb;

    union {
        struct tcp_dpm_pd_request pd_req;
        struct tcp_dpm_pd_request_ex pd_req_ex;

        struct tcp_dpm_dp_data dp_data;
        struct tcp_dpm_custom_vdm_data cvdm_data;

        struct tcp_dpm_svdm_data svdm_data;

        struct pd_get_battery_capabilities gbcdb;
        struct pd_get_battery_status gbsdb;
        struct pd_get_manufacturer_info gmidb;

        uint32_t index;
        uint32_t data_object[PD_DATA_OBJ_SIZE];
    } tcp_dpm_data;
};
struct tcpc_ops {
    int (*init)(bool sw_reset);
    int (*init_alert_mask)(void);
    int (*alert_status_clear)(uint32_t mask);
    int (*fault_status_clear)(uint8_t status);
    int (*set_alert_mask)(uint32_t mask);
    int (*get_alert_mask)(uint32_t *mask);
    int (*get_alert_status)(uint32_t *alert);
    int (*get_power_status)(uint16_t *pwr_status);
    int (*get_fault_status)(uint8_t *status);
    int (*get_cc)(int *cc1, int *cc2);
    int (*set_cc)(int pull);
    int (*set_polarity)(int polarity);
    int (*set_low_rp_duty)(bool low_rp);
    int (*set_vconn)(int enable);
    int (*deinit)(void);
    int (*alert_vendor_defined_handler)(void);
    int (*is_vsafe0v)(void);
//    TODO: used in FOD and Water exception scenarios, to detect CC high voltage
//    int (*set_cc_hidet)(bool en);
//    int (*get_cc_hi)(void);
    int (*set_low_power_mode)(bool en, int pull);
    int (*set_watchdog)(bool en);
    int (*set_intrst)(bool en);
    int (*set_auto_discharge)(bool en);
    int (*set_msg_header)(uint8_t power_role, uint8_t data_role);
    int (*set_rx_enable)(uint8_t enable);
    int (*get_message)(uint32_t *payload,uint16_t *head, enum tcpm_transmit_type *type);
    int (*protocol_reset)(void);
    int (*transmit)(enum tcpm_transmit_type type,uint16_t header, const uint32_t *data);
    int (*set_bist_test_mode)(bool en);
    int (*set_bist_carrier_mode)(uint8_t pattern);
    int (*retransmit)(void);
    int (*set_force_discharge)(bool en, int mv);
    int (*set_vbus)(bool en);
};
struct sgm41620_tcpc {  // tcpc_device
    struct tcpc_ops *ops;
    struct pd_msg msg;
    bool pps_support;
    bool pps_stop;

    uint32_t pending_event;
    bool event_loop_thread_stop;

    /* For TCPC TypeC */
    uint8_t typec_state;
    uint8_t typec_role;
    uint8_t typec_role_new;
    uint8_t typec_attach_old;
    uint8_t typec_attach_new;
    uint8_t typec_local_cc;
    uint8_t typec_local_rp_level;
    uint8_t typec_remote_cc[2];
    uint8_t typec_remote_rp_level;
    uint8_t typec_wait_ps_change;
    bool typec_polarity;
    bool typec_drp_try_timeout;
    bool typec_lpm;
    bool typec_power_ctrl;
    bool typec_is_attached_src;
    int typec_usb_sink_curr;

#if CONFIG_TYPEC_CAP_ROLE_SWAP
    uint8_t typec_during_role_swap;
#endif /* CONFIG_TYPEC_CAP_ROLE_SWAP */

#if CONFIG_TYPEC_CAP_FORCE_DISCHARGE
#if CONFIG_TCPC_FORCE_DISCHARGE_IC
    bool typec_force_discharge;
#endif /* CONFIG_TCPC_FORCE_DISCHARGE_IC */
#endif /* CONFIG_TYPEC_CAP_FORCE_DISCHARGE */

#if CONFIG_TCPC_EXT_DISCHARGE
    bool typec_ext_discharge;
#endif /* CONFIG_TCPC_EXT_DISCHARGE */

    bool pd_pe_running;
    bool pd_wait_pe_idle;
    bool pd_hard_reset_event_pending;
    bool pd_wait_hard_reset_complete;
    bool pd_wait_pr_swap_complete;
    bool pd_ping_event_pending;

    uint32_t tcpc_flags;
    bool pd_bist_mode;
    int pd_transmit_state;

    uint8_t pd_msg_buffer_allocated;
    bool pd_pending_vdm_event;
    bool pd_pending_vdm_reset;
    bool pd_pending_vdm_good_crc;
    bool pd_pending_vdm_discard;
    bool pd_pending_vdm_attention;
    bool pd_postpone_vdm_timeout;

    /* Event */
    uint8_t pd_event_count;
    uint8_t pd_event_head_index;

    struct pd_msg pd_last_vdm_msg;
    struct pd_msg pd_attention_vdm_msg;
    struct pd_event pd_vdm_event;

    struct pd_msg pd_msg_buffer[PD_MSG_BUF_SIZE];
    struct pd_event pd_event_ring_buffer[PD_EVENT_BUF_SIZE];

    uint8_t tcp_event_count;
    uint8_t tcp_event_head_index;
    struct tcp_dpm_event tcp_event_ring_buffer[TCP_EVENT_BUF_SIZE];

    uint8_t tcpc_vconn_supply;
    bool tcpc_source_vconn;
//    uint64_t timer_tick;
    uint8_t pd_wait_vbus_once;

    uint8_t pd_retry_count;

    uint8_t vbus_level;
    bool vbus_safe0v;
    bool vbus_present;
    uint8_t pd_inited_flag;

#if CONFIG_TYPEC_VBUS_CC_SHORT
    bool typec_vbus_to_cc_en;
#endif
#if CONFIG_TYPEC_SNK_DETACH_IGNORE_VBUS
    bool pd_exit_attached_snk_via_cc;
#endif
#if CONFIG_USB_PD_RETRY_CRC_DISCARD
    bool pd_discard_pending;
#endif /* CONFIG_USB_PD_RETRY_CRC_DISCARD */
};

struct pd_port_power_caps {
    uint8_t nr;
    uint32_t pdos[7];
};
struct svdm_svid_list {
    uint8_t cnt;
    uint16_t svids[VDO_MAX_SVID_NR];
};
struct dp_data {
    uint8_t ufp_u_state;
    uint8_t dfp_u_state;

    uint32_t local_status;
    uint32_t remote_status;

    uint32_t local_config;
    uint32_t remote_config;

    uint8_t usb_signal;
    bool active_cable;
    uint8_t cable_signal;
    bool uhbr13_5;
    uint8_t active_component;

    uint16_t cable_svids[DP_ALT_MODE_CABLE_SVIDS_CNT];
    uint8_t cable_svids_cnt;
    uint8_t cable_svids_idx;
};
struct pe_data { /* reset after detached */
    bool pd_connected;
    bool pd_prev_connected;
    bool explicit_contract;
    bool invalid_contract;
    bool modal_operation;

    bool pe_ready;
    bool reset_vdm_state;
    bool power_cable_present;
    bool during_swap; /* pr or dr swap */

#if CONFIG_USB_PD_REV30
    bool cable_rev_discovered;
#endif /* CONFIG_USB_PD_REV30 */  

#if CONFIG_USB_PD_KEEP_PARTNER_ID
    bool partner_id_present;
    uint32_t partner_vdos[VDO_MAX_NR];
#endif /* CONFIG_USB_PD_KEEP_PARTNER_ID */

#if CONFIG_USB_PD_VCONN_SAFE5V_ONLY
    bool vconn_highv_prot;
    uint8_t vconn_highv_prot_role;
#endif /* CONFIG_USB_PD_VCONN_SAFE5V_ONLY */

    uint8_t cap_counter;
    uint8_t discover_id_counter;
    uint8_t hard_reset_counter;

    bool vdm_discard_retry_flag;
    uint8_t vdm_discard_retry_count;

    uint8_t msg_id_rx[3];
    uint8_t msg_id_tx[3];

    uint8_t dpm_reaction_retry;
    uint8_t dpm_svdm_retry_cnt;
    uint16_t dpm_flags;
    uint32_t dpm_reaction_id;
    uint32_t dpm_ready_reactions;
    uint8_t selected_cap;
    uint8_t local_selected_cap;
    uint8_t remote_selected_cap;

    uint8_t pe_state_flags;
    uint8_t pe_state_flags2;
    uint8_t vdm_state_flags;
    uint8_t pe_state_timer;
    uint8_t vdm_state_timer;

#if CONFIG_USB_PD_RECV_HRESET_COUNTER
    uint8_t recv_hard_reset_count;
#endif /* CONFIG_USB_PD_RECV_HRESET_COUNTER */

#if CONFIG_USB_PD_RENEGOTIATION_COUNTER
    uint8_t renegotiation_count;
#endif /* CONFIG_USB_PD_RENEGOTIATION_COUNTER */

    uint8_t cable_discovered_state;
    uint32_t cable_vdos[VDO_MAX_NR];
    struct pd_port_power_caps remote_src_cap;
    struct pd_port_power_caps remote_snk_cap;

#if CONFIG_USB_PD_KEEP_SVIDS
    struct svdm_svid_list remote_svid_list;
#endif /* CONFIG_USB_PD_KEEP_SVIDS */

#if CONFIG_USB_PD_REV30
#if CONFIG_USB_PD_REV30_ALERT_REMOTE
    uint32_t remote_alert;
#endif /* CONFIG_USB_PD_REV30_ALERT_REMOTE */

#if CONFIG_USB_PD_REV30_ALERT_LOCAL
    uint32_t local_alert;
#endif /* CONFIG_USB_PD_REV30_ALERT_LOCAL */

    bool pd_traffic_idle;	/* source only */
    uint8_t pd_traffic_control;
#endif	/* CONFIG_USB_PD_REV30 */

    struct dp_data dp_data;
#if CONFIG_USB_PD_REV30_STATUS_LOCAL
    uint8_t pd_status_event;
#endif	/* CONFIG_USB_PD_REV30_STATUS_LOCAL */

#if CONFIG_USB_PD_DISCARD_AND_UNEXPECT_MSG
    bool pd_sent_ams_init_cmd;
    bool pd_unexpected_event_pending;
    struct pd_event pd_unexpected_event;
#endif	/* CONFIG_USB_PD_DISCARD_AND_UNEXPECT_MSG */

    bool request_rejected;
    uint8_t pd_response_id30_cnt;
};

struct dpm_pdo_info_t {
    uint8_t type;
    uint8_t apdo_type;
    uint8_t pwr_limit;
    int vmin;
    int vmax;
    int uw;
    int ma;
};
struct svdm_mode {
    uint8_t mode_cnt;
    uint32_t mode_vdo[VDO_MAX_NR];
};
struct svdm_svid_data {
    bool exist;
    uint16_t svid;
    struct svdm_svid_list cable_svids;
    uint8_t active_mode;
    struct svdm_mode local_mode;
    struct svdm_mode remote_mode;
    const struct svdm_svid_ops *ops;
};
struct pd_source_cap_ext {
    uint16_t vid;
    uint16_t pid;
    uint32_t xid;
    uint8_t fw_ver;
    uint8_t hw_ver;
    uint8_t voltage_regulation;
    uint8_t hold_time_ms;
    uint8_t compliance;	/* bit field */
    uint8_t touch_current;	/* bit field */
    uint16_t peak_current[3];
    uint8_t touch_temp;
    uint8_t source_inputs;	/* bit field */
    uint8_t batteries;
    uint8_t source_pdp;
    uint8_t epr_source_pdp;
};
struct pd_sink_cap_ext {
    uint16_t vid;
    uint16_t pid;
    uint32_t xid;
    uint8_t fw_ver;
    uint8_t hw_ver;
    uint8_t skedb_ver;
    uint8_t load_step;
    uint16_t load_char;
    uint8_t compliance;
    uint8_t touch_temp;
    uint8_t battery_info;
    uint8_t sink_modes;
    uint8_t min_pdp;
    uint8_t oper_pdp;
    uint8_t max_pdp;
    uint8_t epr_min_pdp;
    uint8_t epr_oper_pdp;
    uint8_t epr_max_pdp;
};
#if CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY
struct pd_country_authority {
    uint16_t code;
    uint8_t len;
    uint8_t *data;
};
#endif /* CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY */
struct pd_manufacturer_info {
    uint16_t vid;
    uint16_t pid;
    uint8_t mfrs_string[PD_MIDB_DYNAMIC_SIZE];
};
struct pd_battery_capabilities {
    uint16_t vid;
    uint16_t pid;
    uint16_t bat_design_cap;
    uint16_t bat_last_full_cap;
    uint8_t bat_type;
};
#if CONFIG_USB_PD_REV30_BAT_INFO
struct pd_battery_info {
    uint32_t bat_status;
    struct pd_manufacturer_info mfrs_info;
    struct pd_battery_capabilities bat_cap;
};
#endif /* CONFIG_USB_PD_REV30_BAT_INFO */
struct pd_port {
    /* PD */
    bool msg_output_lock;

    uint8_t state_machine;
    uint8_t pd_connect_state;

    uint8_t pe_pd_state;
    uint8_t pe_vdm_state;

    uint8_t pe_state_next;
    uint8_t pe_state_curr;

    uint8_t data_role;
    uint8_t power_role;
    uint8_t vconn_role;

    struct pe_data pe_data;

#if CONFIG_USB_PD_ERROR_RECOVERY_ONCE
    uint8_t error_recovery_once;
#endif /* CONFIG_USB_PD_ERROR_RECOVERY_ONCE */

#if CONFIG_USB_PD_REV30
    bool pps_request_stop;
#if CONFIG_USB_PD_REV30_SYNC_SPEC_REV
    uint8_t pd_revision[2];
    uint8_t svdm_ver_min[2];
#endif /* CONFIG_USB_PD_REV30_SYNC_SPEC_REV */
#endif /* CONFIG_USB_PD_REV30 */

#if CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP
    uint8_t msg_id_pr_swap_last;
#endif	/* CONFIG_USB_PD_IGNORE_PS_RDY_AFTER_PR_SWAP */

    struct dpm_pdo_info_t last_sink_pdo_info;
    uint32_t last_rdo;

    uint8_t id_vdo_nr;
    uint32_t id_vdos[VDO_MAX_NR];

#if CONFIG_USB_PD_REV30
    uint32_t id_header;
#endif /* CONFIG_USB_PD_REV30 */

    uint8_t svid_data_cnt;
    struct svdm_svid_data *svid_data;

    /* DPM */
    int request_v;
    int request_i;
    int request_v_new;
    int request_i_new;
    int request_i_op;
    int request_i_max;

#if CONFIG_USB_PD_REV30_PPS_SINK
    int request_v_apdo;
    int request_i_apdo;
    bool request_apdo;
    bool request_apdo_new;
#endif /* CONFIG_USB_PD_REV30_PPS_SINK */

    struct pd_port_power_caps local_src_cap;
    struct pd_port_power_caps local_snk_cap;
    struct pd_port_power_caps local_src_cap_default;

#if CONFIG_USB_PD_REV30_PPS_SINK
    uint8_t local_snk_cap_nr_pd30;
    uint8_t local_snk_cap_nr_pd20;
#endif /* CONFIG_USB_PD_REV30_PPS_SINK */

    uint16_t mode_svid;
    uint8_t mode_obj_pos;
    uint16_t cable_mode_svid;
    uint8_t cable_mode_obj_pos;
    uint16_t cable_svid_to_discover;

    uint32_t dpm_caps;

    uint8_t dpm_charging_policy;
    uint8_t dpm_charging_policy_default;

    /* ALT Mode */
//#ifdef CONFIG_USB_PD_ALT_MODE
#if 1
    uint8_t dp_first_connected;
    uint8_t dp_second_connected;
#endif /* CONFIG_USB_PD_ALT_MODE */

    bool cvdm_wait_resp;
    bool cvdm_cable;
    uint8_t cvdm_cnt;
    uint32_t cvdm_data[PD_DATA_OBJ_SIZE];
    uint16_t cvdm_svid;

#if CONFIG_USB_PD_CUSTOM_VDM
    bool uvdm_wait_resp;
    uint8_t uvdm_cnt;
    uint16_t uvdm_svid;
    uint32_t uvdm_data[PD_DATA_OBJ_SIZE];
#endif /* CONFIG_USB_PD_CUSTOM_VDM */

#if CONFIG_USB_PD_ALT_MODE_RTDC
    uint8_t dc_dfp_state;
    uint32_t dc_pass_code;
#endif /* CONFIG_USB_PD_ALT_MODE_RTDC */

#if CONFIG_USB_PD_CUSTOM_DBGACC
    bool custom_dbgacc;
#endif /* CONFIG_USB_PD_CUSTOM_DBGACC */

#if CONFIG_USB_PD_RICHTEK_UVDM
    bool richtek_init_done;
#endif /* CONFIG_USB_PD_RICHTEK_UVDM */

    struct tcp_dpm_event tcp_event;
    uint8_t tcp_event_id_1st;

#if CONFIG_USB_PD_TCPM_CB_2ND
    uint8_t tcp_event_id_2nd;
    bool tcp_event_drop_reset_once;

    uint8_t *tcpm_bk_cb_data;
    uint8_t tcpm_bk_cb_data_max;
#endif /* CONFIG_USB_PD_TCPM_CB_2ND */

#if CONFIG_USB_PD_BLOCK_TCPM
    int tcpm_bk_ret;
    bool tcpm_bk_done;
    uint8_t tcpm_bk_event_id;	
#endif /* CONFIG_USB_PD_BLOCK_TCPM */

    /* curr_event info */
    bool curr_is_vdm_evt;
    struct pd_event curr_pd_event;

    uint16_t pd_msg_data_size;
    uint8_t pd_msg_data_count;
    uint8_t *pd_msg_data_payload;

    uint8_t	curr_vdm_ops;
    uint16_t curr_vdm_svid;

    uint16_t curr_msg_hdr;
    uint32_t curr_vdm_hdr;

    uint8_t curr_ready_state;
    uint8_t curr_hreset_state;
    uint8_t curr_sreset_state;

    bool curr_unsupported_msg;

#if CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL
    struct pd_source_cap_ext src_cap_ext;
#endif	/* CONFIG_USB_PD_REV30_SRC_CAP_EXT_LOCAL */

#if CONFIG_USB_PD_REV30
    struct pd_sink_cap_ext snk_cap_ext;
#endif	/* CONFIG_USB_PD_REV30 */

#if CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL
    struct pd_manufacturer_info mfrs_info;
#endif	/* CONFIG_USB_PD_REV30_MFRS_INFO_LOCAL */

#if CONFIG_USB_PD_REV30_BAT_INFO
    uint32_t pid;
    uint32_t vid;
    uint8_t bat_nr;
    struct pd_battery_info *fix_bat_info;
    struct pd_battery_info *swap_bat_info;
#endif	/* CONFIG_USB_PD_REV30_BAT_INFO */

#if CONFIG_USB_PD_REV30_STATUS_LOCAL
    uint8_t pd_status_bat_in;
    uint8_t pd_status_present_in;
#if CONFIG_USB_PD_REV30_STATUS_LOCAL_TEMP
    uint8_t pd_status_temp;
    uint8_t pd_status_temp_status;
#endif /* CONFIG_USB_PD_REV30_STATUS_LOCAL_TEMP */
#endif /* CONFIG_USB_PD_REV30_STATUS_LOCAL */

#if CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY
    uint8_t country_nr;
    struct pd_country_authority *country_info;
#endif /* CONFIG_USB_PD_REV30_COUNTRY_AUTHORITY */
};
struct svdm_svid_ops {
    const char *name;
    uint16_t svid;
    struct svdm_svid_list cable_svids;
    bool (*dfp_inform_id)(struct pd_port *pd_port, struct svdm_svid_data *svid_data, bool ack);
    bool (*dfp_inform_svids)(struct pd_port *pd_port, struct svdm_svid_data *svid_data, bool ack);
    bool (*dfp_inform_modes)(struct pd_port *pd_port, struct svdm_svid_data *svid_data, bool ack);
    bool (*dfp_inform_enter_mode)(struct pd_port *pd_port, struct svdm_svid_data *svid_data, uint8_t ops, bool ack);
    bool (*dfp_inform_exit_mode)(struct pd_port *pd_port, struct svdm_svid_data *svid_data, uint8_t ops);
    bool (*dfp_inform_attention)(struct pd_port *pd_port, struct svdm_svid_data *svid_data);
    bool (*dfp_inform_cable_id)(struct pd_port *pd_port,
         struct svdm_svid_data *svid_data, bool ack,
         uint32_t *payload, uint8_t cnt);
    bool (*dfp_inform_cable_svids)(struct pd_port *pd_port,
         struct svdm_svid_data *svid_data, bool ack,
         uint32_t *payload, uint8_t cnt);
    bool (*dfp_inform_cable_modes)(struct pd_port *pd_port,
         struct svdm_svid_data *svid_data, bool ack,
         uint32_t *payload, uint8_t cnt);
    bool (*ufp_request_enter_mode)(struct pd_port *pd_port, struct svdm_svid_data *svid_data, uint8_t ops);
    bool (*ufp_request_exit_mode)(struct pd_port *pd_port, struct svdm_svid_data *svid_data, uint8_t ops);
    bool (*notify_pe_startup)(struct pd_port *pd_port, struct svdm_svid_data *svid_data);
    bool (*notify_pe_ready)(struct pd_port *pd_port, struct svdm_svid_data *svid_data);
    bool (*notify_pe_shutdown)(struct pd_port *pd_port, struct svdm_svid_data *svid_data);
    bool (*dfp_notify_cvdm)(struct pd_port *pd_port, struct svdm_svid_data *svid_data, bool ack);
    bool (*ufp_notify_cvdm)(struct pd_port *pd_port, struct svdm_svid_data *svid_data);
    bool (*reset_state)(struct pd_port *pd_port, struct svdm_svid_data *svid_data);
    bool (*parse_svid_data)(struct pd_port *pd_port, struct svdm_svid_data *svid_data);
};

struct pe_state_transition {
    uint8_t curr_state; /*state, msg, or cmd */
    uint8_t next_state;
};
struct pe_state_reaction {
    uint16_t nr_transition;
    const struct pe_state_transition *state_transition;
};

struct sgm_device_info {
    bool ufcs_support;
    bool pd_support;
    uint16_t chip_id;
};
/************************* STRUCT ************************/

/************************* GLOBAL ************************/
extern struct tcpc_ops sgm41620_tcpc_ops;
extern struct sgm41620_tcpc g_tcpc_dev;
extern struct sgm41620_tcpc *p_tcpc_dev;
extern struct pd_port g_pd_port;
extern struct pd_port *p_pd_port;
extern struct sgm_device_info sgm_dev;
extern volatile uint32_t g_sys_ticks;
/************************* GLOBAL ************************/

#endif // COMMON_H
